package bev.frames.client;

import java.awt.*;
import java.awt.event.*;

import javax.swing.*;

import bev.AppManager;
import bev.ConnectionManager;
import bev.article.BaseArticle;
import bev.query.ArticleQuery;

public class ClientFrame extends JFrame {
    private static final long serialVersionUID = 2879061299608434667L;

    // App and client data.
    AppManager appManager;
    BaseArticle currentArticle = null;

    // Visual components.
    MenuBar menuBar;
    ToolBar toolBar;
    SearchPane searchPane;
    ArticlePane articlePane;

    public ClientFrame( AppManager appManager ) {
        super( "Bird's Eye View" );

        // Parent AppManager.
        this.appManager = appManager;

        // Configure frame.
        setSize( 1024, 768 );
        setMinimumSize( new Dimension( 640, 480 ) );
        setLocationRelativeTo( null );
        setDefaultCloseOperation( JFrame.DO_NOTHING_ON_CLOSE );
        addWindowListener( new WindowAdapter() {
            @Override
            public void windowClosing( WindowEvent e ) {
                ( (ClientFrame) e.getWindow() ).promptClose();
            }
        } );

        // Use grid bag layout.
        getContentPane().setLayout( new GridBagLayout() );

        // Menu bar.
        menuBar = new MenuBar( this );
        setJMenuBar( menuBar.getMenuBar() );

        // Tool bar.
        GridBagConstraints gbcToolBar = new GridBagConstraints();
        gbcToolBar.fill = GridBagConstraints.HORIZONTAL;
        gbcToolBar.gridx = 0;
        gbcToolBar.gridwidth = 3;
        gbcToolBar.gridy = 0;
        gbcToolBar.weightx = 1.0;
        gbcToolBar.weighty = 0.0;
        toolBar = new ToolBar( this );
        toolBar.setFloatable( false );
        add( toolBar, gbcToolBar );

        // Main panels (search and article panels).
        GridBagConstraints gbcMainPanel = new GridBagConstraints();
        gbcMainPanel.fill = GridBagConstraints.BOTH;
        gbcMainPanel.gridx = 0;
        gbcMainPanel.gridy = 1;
        gbcMainPanel.weightx = 1.0;
        gbcMainPanel.weighty = 1.0;
        add( this.buildMainPanels(), gbcMainPanel );
    }

    // Builds and returns the client frame's main panels (search and article
    // panels).
    private JSplitPane buildMainPanels() {
        JSplitPane mainPane = new JSplitPane( JSplitPane.HORIZONTAL_SPLIT );

        // Search panel.
        searchPane = new SearchPane( this );
        mainPane.setLeftComponent( searchPane );

        // Article panel.
        articlePane = new ArticlePane( this );
        mainPane.setRightComponent( articlePane );

        return mainPane;
    }

    public void setCurrentArticle( BaseArticle newArticle ) {
        if ( articlePane.getEditMode() ) {
            int results = JOptionPane.showConfirmDialog( this,
                    "Are you sure you want to cancel any changes?",
                    "Ignore Changes?", JOptionPane.OK_CANCEL_OPTION );

            if ( results != 0 )
                return;
        }

        currentArticle = newArticle;
        articlePane.setEditMode( false );
        articlePane.refreshView();
    }

    // Allows components of the ClientFrame to universally access the current
    // article in memory.
    public BaseArticle getCurrentArticle() {
        return currentArticle;
    }

    public void connectToDatabaseByFile( String filePath ) {
        if ( !ConnectionManager.readConnectionFile( filePath ) )
            JOptionPane.showMessageDialog( this,
                    "Failed to connect to a database using this file." );
    }

    public void onConnectionSet() {
        // Run a general query to pull ALL articles from the database each
        // time a new database connection is set (for a 'default' list).
        runQuery( new ArticleQuery( "" ) );
    }

    // Run a query to update the search list by passing an ArticleQuery object
    // with the information defining what to pull from the database. This is the
    // ClientFrame-level runQuery(), which is the universal method that any
    // component
    // with access to the ClientFrame can use to request a query be run.
    public void runQuery( ArticleQuery query ) {
        searchPane.runQuery( query );
    }

    // Changes the filtering applied to the article list visible in the search
    // pane. Specified by passing in an EnumSet of ArticleType containing the
    // enumerations for articles to be made visible (i.e. PERSON, PLACE, etc.).
    public void filterArticleView() {
        searchPane.filterArticleView( toolBar.getArticleFilterTypes() );
    }

    // Closes the frame, but only after the user is prompted about it and
    // accepts.
    public void promptClose() {
        int results = JOptionPane.showConfirmDialog( this,
                "Are you sure you want to exit?", "Exit Application?",
                JOptionPane.OK_CANCEL_OPTION );
        if ( results == 0 ) {
            this.close();
        }
    }

    // Closes the frame without prompting the user.
    public void close() {
        try {
            // Use official application shutdown.
            appManager.shutdown();
        } catch ( Exception ex ) {
            ex.printStackTrace();
        }
    }
}
